// ignore_for_file: avoid_print

import 'dart:isolate';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:opencv_dart/opencv_dart.dart' as cv;
import 'package:image_picker/image_picker.dart';

class OpencvTestPage extends StatefulWidget {
  const OpencvTestPage({super.key});

  @override
  State<OpencvTestPage> createState() => _TestState();
}

class _TestState extends State<OpencvTestPage> {
  var images = <Uint8List>[];

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
  }

  // native resources are unsendable for isolate, so use raw data or encoded Uint8List and convert back
  Future<Uint8List> heavyTask(Uint8List buffer) async => Isolate.run(() {
        final im = cv.imdecode(buffer, cv.IMREAD_COLOR);
        late cv.Mat gray;
        gray = cv.cvtColor(im, cv.COLOR_BGR2GRAY);
        return cv.imencode(".png", gray).$2;
      });

  Future<cv.Mat> heavyTaskAsync(cv.Mat im) async {
    late cv.Mat gray;
    gray = await cv.cvtColorAsync(im, cv.COLOR_BGR2GRAY);
    // for (var i = 0; i < 1000; i++) {
    // }
    return gray;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('OpenCV Test'),
      ),
      body: Container(
        alignment: Alignment.center,
        child: Column(
          children: [
            ElevatedButton(
              onPressed: () async {
                final picker = ImagePicker();
                final img = await picker.pickImage(source: ImageSource.gallery);
                if (img != null) {
                  final path = img.path;
                  final mat = cv.imread(path);
                  print(
                      "cv.imread: width: ${mat.cols}, height: ${mat.rows}, path: $path");
                  final (success, bytes) = cv.imencode(".png", mat);
                  print("imencode: $success, ${bytes.length}");
                  // heavy computation
                  final gray = await heavyTask(bytes);
                  setState(() {
                    images = [bytes, gray];
                  });
                }
              },
              child: const Text("Pick Image"),
            ),
            ElevatedButton(
              onPressed: () async {
                final data = await DefaultAssetBundle.of(context)
                    .load("assets/images/2.png");
                final bytes = data.buffer.asUint8List();
                // heavy computation
                // final (gray, blur) = await heavyTask(bytes);
                // setState(() {
                //   images = [bytes, gray, blur];
                // });
                final gray =
                    await heavyTaskAsync(cv.imdecode(bytes, cv.IMREAD_COLOR));
                setState(() {
                  images = [
                    bytes,
                    cv.imencode(".png", gray).$2,
                  ];
                });
              },
              child: const Text("Process"),
            ),
            Expanded(
              flex: 2,
              child: Row(
                children: [
                  Expanded(
                    child: ListView.builder(
                      itemCount: images.length,
                      itemBuilder: (ctx, idx) => Card(
                        child: Image.memory(images[idx]),
                      ),
                    ),
                  ),
                  Expanded(
                    child: SingleChildScrollView(
                      child: Text(cv.getBuildInformation()),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}
